package com.example.security.demo.config;

import cn.hutool.http.HttpStatus;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.security.demo.constant.CommonConstant;
import com.example.security.demo.dto.UserDto;
import com.example.security.demo.service.TokenService;
import com.example.security.demo.vo.R;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Service;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author zhanpengguo
 * @date 2019-10-15 10:14
 */
@Slf4j
@Service
@AllArgsConstructor
public class SecurityHandler implements AuthenticationSuccessHandler, AuthenticationFailureHandler, AuthenticationEntryPoint, AccessDeniedHandler, LogoutSuccessHandler {
    private final TokenService tokenService;
    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        log.error("登录失败");
        response(httpServletResponse,new R(new Throwable(e.getMessage())));
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        log.info("登录成功,用户信息：{}", JSONObject.toJSONString(authentication));
        UserDto userDto = (UserDto) authentication.getPrincipal();
        String token = tokenService.saveToken(userDto);
        response(httpServletResponse,new R(token, "登录成功"));
    }

    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        log.error("未登录");
        response(httpServletResponse,new R(new Throwable("未登录")));
    }

    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
        log.error("无权限");
        response(httpServletResponse,new R(new Throwable(e.getMessage())));
    }

    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        log.info("退出登录成功");
        String token = httpServletRequest.getHeader(CommonConstant.TOKEN);
        try {
            tokenService.deleteToken(token);
        } catch (Exception e) {
            log.error("删除token失败", e);
            response(httpServletResponse,new R(new Throwable("退出失败" + e.getMessage())));
            return;
        }
        response(httpServletResponse,new R(token, "退出成功"));
    }

    private void response(HttpServletResponse response, R r) throws IOException{
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(JSONObject.toJSONString(r));
    }
}
